angular.module('zixys.directives',[])

    .directive('zixysMainWrapper', [function() {

        return {
            restrict: 'C',
            replace: false,
            scope: {},
            template:'<div id="zixys-wrap">'+
                        '<div id="zixys-tab-wrap"></div>'+
                        '<div id="zixys-content-wrap"></div>'+
                        '<span class="zixys-style"></span>'+
                     '</div>',

            controller: ['$scope','$element','$compile',function(scope, element, $compile) {

                scope.$root.$contentWrapper = element.find('#zixys-content-wrap');
                scope.$root.$tabsWrapper = element.find('#zixys-tab-wrap');
                
                scope.$root.addTab = function(tabTitle,contentName){
                    
                    var tab = $('<span class="zixys-tab" src="zixys-'+contentName+'">'+tabTitle+'</div>');
                    var content = $('<div id="zixys-'+contentName+'" class="'+contentName+'" ></div>');
                    scope.$root.$contentWrapper.append(content);
                    scope.$root.$tabsWrapper.append(tab);
                    
                    $compile(content)(scope.$root);
                    $compile(tab)(scope.$root);
                };
                
                scope.$root.addButton = function(buttonTitle,className){
                    var button = $('<b class="'+className+' zixys-button" title="'+buttonTitle+'"></b>');
                    scope.$root.$tabsWrapper.prepend(button);
                    $compile(button)(scope.$root);
                }
                
                scope.$root.$broadcast('zixysDomReady', {
                    contentWrapper:scope.$root.$contentWrapper,
                    tabsWrapper:scope.$root.$tabsWrapper
                })    
            }]
        }
        
    }])

    .directive('zixysTab',function(){
        return {
            restrict: 'C',
            replace: false,
            scope: {},

            link: function($scope, element, attrs) {
                var contentWrapper = $scope.$root.$contentWrapper;
                var tabContent = contentWrapper.find('#'+attrs.src);
                var tabWrapper = $scope.$root.$tabsWrapper;
                
                element.click(function(){
                    tabWrapper.children().removeClass('zActive');
                    element.addClass('zActive');
                    contentWrapper.children().hide();
                    tabContent.show();
                    $scope.$root.$activeTab = tabContent;
                }); 
                
                //make first tab active
                tabWrapper.children('span.zixys-tab:eq(0)').addClass('zActive');
                $scope.$root.$activeTab = contentWrapper.children().hide().filter(':eq(0)');
                $scope.$root.$activeTab.show();
                $scope.$root.$broadcast('tabsReady',$scope.$root.$activeTab);
            }
        }
    })
    
    .directive('zixysInnerTab',function(){
        return {
            restrict: 'C',
            replace: false,
            scope: {},
            link:function($scope, element, attrs){
                    var parent = element.parent(),
                        tabs = element.children(),
                        contents = parent.find('#'+attrs.src).children();
                        
                    tabs.click(function(){
                        var self = this;
                        var index = 0;
                        tabs.each(function(i,elem){
                           if(elem === self){
                               index = i;
                               return false;
                           } 
                        });
                        contents.hide();
                        contents.filter(':eq('+index+')').show();
                        tabs.removeClass('zActive').filter(':eq('+index+')').addClass('zActive');
                    });
                    
                    contents.hide().filter(':eq(0)').show();
                    tabs.filter(':eq(0)').addClass('zActive');

            }
        }
    })
    
    .directive('zixysButton',function(){
        return {
            restrict: 'A',
            replace: true,
            template:'<em class="zixys-button"><i></i></em>',
            scope: {
                button:'=zixysButton'
            },

            link: function($scope, element, attrs) {
                var defaults ={
                    iconClass:'',
                    onPress: angular.noop,
                    onRelease: angular.noop,
                    disable:false
                }, disabled;
                $scope.button = $.extend({}, defaults, $scope.button);
                element.children().addClass($scope.button.iconClass);
                
                element.click(function(event){
                    if(disabled) return;
                    if(element.hasClass('zixys-sbutton-pressed')){
                        element.removeClass('zixys-sbutton-pressed');
                        $scope.button.onPress();
                    }else{
                        element.addClass('zixys-sbutton-pressed');
                        $scope.button.onRelease();
                    }
                    event.stopImmediatePropagation();
                });

                $scope.button.press = function(){
                    if(disabled) return;
                    if(!element.hasClass('zixys-sbutton-pressed')){
                        element.addClass('zixys-sbutton-pressed');
                        $scope.button.onPress();
                    }
                }

                $scope.button.release = function(){
                    if(disabled) return;
                    if(element.hasClass('zixys-sbutton-pressed')){
                        element.removeClass('zixys-sbutton-pressed');
                        $scope.button.onRelease();
                    }                    
                }

                $scope.button.enable = function(){
                   element.removeClass('zixys-sbutton-disabled');
                    disabled = false;
                }
                
                $scope.button.disable = function(){
                    $scope.button.release();
                    element.addClass('zixys-sbutton-disabled');
                    disabled = true;
                }
                
                $scope.button.isEnable = function(){
                    return !disabled;
                }
                
                $scope.button.isPressed = function(){
                    return element.hasClass('zixys-sbutton-pressed');
                }                
                
                if($scope.button.initStateDisabled){
                    $scope.button.disable();
                }
            }
        }
    })
    
    .directive('zixysSpinner',function(){
        return {
            restrict: 'C',

            link:function ($scope, element, attr) {
                var model = attr['ngModel'];
                if(!model) return;

                var spinner = new zixysSpinner(element,$scope,model);

                element.keydown(function(event){

                    switch(event.keyCode)
                    {
                    case 38:
                        spinner.increment = 1;
                        break;
                    case 40:
                        spinner.increment = -1;
                        break;
                    default:
                        return;
                    }

                    if(spinner.isSpinning){
                        return;
                    }else{
                        spinner.isSpinning = true;
                    }
                    
                    spinner.start();

                }).keyup(function(event){
                    spinner.stop();
                    if( (event.keyCode!=38)&&(event.keyCode!=38) ){
                        spinner.singleRun();
                    }
                }).blur(function(){
                    spinner.stop();
                });

            }
        }
    })
    
    .directive('colorpick',['Colors', function(Colors){
        return {
            restrict: 'A',
            replace: true,
            template:'<span>\n\
                        <input ng-disabled="disabled" type="text" class="zixys-colorpicker">\n\
                        <span class="zixys-color-prev" disabled="disabled" percentslider="output.alpha">\n\
                            <b></b>\n\
                        </span>\n\
                    </span>',
            scope: {
                output:'=colorpick',
                disabled : '=ngDisabled'
            },
            link : function ($scope, element, attr) {
                var input = element.children('input'),
                    previewer = element.find('b'),
                    picker;

                //defaults
                function setRgb(rgb) {
                    if(!$scope.output) {
                        $scope.output = Colors.getColor();
                    }
                    $scope.output.rgb =rgb;
                }

                function setBackground(){
                    if($scope.output.rgb && $scope.output.alpha) {
                        previewer[0].style.background = Colors.stringifyColor($scope.output);
                    }
                };

                function reset(){
                    input.val('');
                    previewer[0].style.background = '#fff';
                }
                
                input.ColorPicker({
                    onSubmit: function(hsb, hex, rgb, el) {
                        el.value = hex;
                        $(el).ColorPickerHide();
                        setRgb(rgb);
                        setBackground();
                    },
                    onBeforeShow: function (picker) {
                        if($scope.disabled) return false;
                        input.ColorPickerSetColor(this.value);
                    },
                    onChange : function(hsb, hex, rgb){
                        input[0].value=hex;
                        setRgb(rgb);
                        $scope.$apply();
                        setBackground();
                    }
                }).bind('keyup',function(){
                    input.ColorPickerSetColor(this.value);
                    setRgb(Colors.HexToRGB(this.value));
                    setBackground();
                    $scope.$apply('output');
                });

                $scope.$watch("output.alpha", function(newVal){
                    if(!newVal) return;
                    setBackground();
                });

                $scope.$watch("output.rgb", function(newVal){
                    if(!newVal) return;
                    input.val(Colors.RGBToHex(newVal));
                    setBackground();
                });

                $scope.$watch("output",function(newVal){
                    if(!newVal) {
                        reset();
                    }
                });

                picker = $('body>#'+input.data('colorpickerId'))
                //fix z-index
                picker.css('z-index','999999');
           }
        }
    }])

    .directive('pagination', function() {

        return {
            restrict: 'A',
            replace: true,
            scope: {
                pagination:'=pagination'
            },
            template:'<div class="pagination">'+
                        '<input class="btn" ng-disabled="isFirstPage" type="button" ng-click="first()" value="<<" />' +
                        '<input class="btn" ng-disabled="isFirstPage" type="button" ng-click="previews()" value="<" />' +
                        '<select ng-change="changePerPage()" ng-model="perPage" ng-options="c for c in pageSets"></select>' +
                        '<input class="btn" ng-disabled="isLastPage" type="button" ng-click="next()" value=">" />' +
                        '<input class="btn" ng-disabled="isLastPage" type="button" ng-click="last()" value=">>" />' +
                     '</div>',

            link: function(scope, element, attrs) {

            },
            controller : ['$scope',function($scope){
                var totalItems, currentPage, defaults, totalPages;

                $scope.startAt = 0;
                $scope.perPage = 10;
                $scope.isFirstPage = true;
                $scope.isLastPage = false;
                $scope.pageSets = [10,20,50]

                //$scope.pagination = angular.extend(defaults, $scope.pagination);

                function getTotalPages(totalItems, perPage){
                    return Math.ceil(totalItems/perPage);
                }

                function getCurrentPage(startAt, perPage){
                    return Math.floor($scope.startAt/$scope.perPage)+1;
                }

                function loadSet(){
                    if(angular.isNumber($scope.startAt) && angular.isNumber($scope.perPage) ){
                        $scope.pagination.totalPages = totalPages;
                        $scope.pagination.currentPage = getCurrentPage();
                        $scope.pagination.loadSet($scope.startAt, $scope.perPage);
                    }
                }

                $scope.first = function(){
                    $scope.startAt = 0;
                    loadSet();
                };

                $scope.last = function(){
                    $scope.startAt = (totalPages -1) * $scope.perPage;
                    loadSet();
                };

                $scope.previews = function(){
                    $scope.startAt = $scope.startAt - $scope.perPage;
                    loadSet();
                };

                $scope.next = function(){
                    $scope.startAt = $scope.startAt + $scope.perPage;
                    loadSet();
                };

                $scope.changePerPage = function(){
                    $scope.startAt = 0;
                    totalPages = getTotalPages(totalItems, $scope.perPage);
                    loadSet();
                };

                $scope.$watch('startAt',function(newVal){
                    if(!angular.isNumber(newVal)) return;

                    if($scope.startAt + $scope.perPage > totalItems){
                        $scope.isLastPage = true;
                    }else{
                        $scope.isLastPage = false;
                    }

                    if($scope.startAt - $scope.perPage < 0) {
                        $scope.isFirstPage = true;
                    }else{
                        $scope.isFirstPage = false;
                    }

                });

                $scope.$watch('pagination.totalItems',function(newVal){
                    if(angular.isNumber(newVal)){
                        totalItems = newVal;
                        totalPages = getTotalPages(totalItems, $scope.perPage);
                        loadSet();
                    }
                });

            }]
        }

    })

    .directive('percentslider',['$compile','$rootScope',function($compile,$rootScope){
        return {
            restrict: 'A',
            replace: false,
            scope: {
                output:'=percentslider',
                disabled:'=ngDisabled'
            },
            link:function($scope, element, attr){

                var slider = '<div class="zx__ zixys-slider zixys-hidden" style="z-index:999999">\n\
                                <div class="zixys-slide-bg">\n\
                                    <b style="bottom:{{output}}%"></b>\n\
                                </div>\n\
                                <div class="zixys-slider-input"><input class="zixys-input zixys-spinner" min="0" max="100" ng-model="output" />%\n\
                                </div>\n\
                             </div>';
                
                slider = $compile(slider)($scope);
                slider.appendTo('body');

                var slideBtn = slider.find('b'),
                    slideContainer = slideBtn.parent(),
                    sliderInput = slider.find('input'),
                    scale = slideContainer.height() - slideBtn.outerHeight(),
                    doc = $(document);

                element.click(function(event) {
                    if ( !$.isNumeric($scope.output) ) return;

                    doc.trigger('click');
                    if(slider.hasClass('zixys-hidden')){
                        show();
                    }else{
                        hide();
                    }
                    event.stopPropagation();
                });
                
                function show (){
                    var position = element.offset();
                    slider.css({
                        left : position.left + element.width() + 10,
                        top : position.top - slider.height()/2 + element.height()/2
                    });
                    bindDraggables();
                    slider.removeClass('zixys-hidden');
                };
                
                function hide (){
                    unbindDraggables();
                    slider.addClass('zixys-hidden');
                };
                
 
                function mouseMove(event) {
                    var d = event.pageY - slideContainer.offset().top;
                               
                    if( d>scale){
                        d = scale;
                    }else if(d<0){
                        d = 0;
                    }

                    var val = parseInt((100*Math.abs(scale-d))/scale);
                    //$scope.pos = d;
                    $scope.output = val;
                    $scope.$apply('output');
                };
                
                function bindDraggables () {
                    doc.bind('mousedown.zixysSlider',function(event){
                        if(event.target === slideBtn[0] || event.target === slideContainer[0] ){
                            
                            doc.bind('mousemove.zixysSlider',mouseMove);
                            mouseMove(event);
                            // cancel out any text selections 
                            document.body.focus(); 
                            // prevent text selection in IE 
                            document.onselectstart = function () { return false; }; 
                            return false;
                        }
                    }).bind('mouseup.zixysSlider',function(event){
                        // we're done with these events until the next OnMouseDown 
                        document.onmousemove = undefined; 
                        document.onselectstart = undefined;
                        doc.unbind('mousemove.zixysSlider');
                    }).bind('click.zixysSlider',function(){
                        hide();
                    });                   
                };
                
                function unbindDraggables () {
                    doc.unbind('mousedown.zixysSlider','mousemove.zixysSlider','click.zixysSlider');
                }
                
                slider.bind('click.zixysSlider',function(e){
                    e.stopPropagation();
                });
            }
        }
    }])

    .directive('selectList',['$compile',function($compile){
        return {
            restrict: 'A',
            template: '<div class="zixys-select-list">' +
                      '</div>',
            replace : true,
            scope : {
                output : '=selectList',
                source : '=source',
                item : '@item',
                options : '=options'
            },
            link : function ($scope, element, attr) {
                var ul = '<ul class="zixys-select-ul">' +
                            '<li ng-repeat="item in source" ng-class="{zixysSelListItem : item == output}" ng-click="selectItem(item)">' +
                                '{{item.'+attr['item']+'}}' +
                                '<i ng-class="{zx_icon:true, zx_i_dl:true}" ng-show="opts.remove" ng-click="delete(item)" title="Delete"></i>' +
                                '<i ng-class="{zx_icon:true, zx_i_vw:true, disabled : item.view == false}" ng-show="opts.view" ng-click="view(item)" title="Show / Hide"></i>' +
                                '<i ng-class="{zx_icon:true, zx_i_dw:true, disabled:$last}" ng-show="opts.arrows && !sourceIsObject" ng-click="moveDown(item, $last)" title="Move Down"></i>' +
                                '<i ng-class="{zx_icon:true, zx_i_up:true, disabled:$first}" ng-show="opts.arrows && !sourceIsObject" ng-click="moveUp(item, $first)" title="Move Up"></i>' +
                            '</li>' +
                        '</ul>';

                element.append($compile(ul)($scope));

                $scope.selectItem = function(item) {
                    $scope.output = item;
                }

            },
            controller : ['$scope', function($scope) {

                var defaults = {
                    remove : true,
                    view : true,
                    arrows : true
                }
                $scope.sourceIsObject = false;
                $scope.opts = defaults;

                function getIndexByItem(item){
                    for (var i=0; i<$scope.source.length; i++) {
                        if ($scope.source[i] === item) {
                            return i;
                        }
                    }
                }

                function getKeyByItem(item){
                    for (var key in $scope.source) {
                        if ($scope.source[key] === item) {
                            return key;
                        }
                    }
                }

                $scope.delete = function (item) {
                    if(item.$_delete){
                        item.$_delete();
                    };

                    if($.isArray($scope.source)) {
                        var index = getIndexByItem(item);
                        if (index >0 ) {
                            $scope.source.splice(index,1);
                        }
                        $scope.output = null;
                    } else
                    if ($.isPlainObject($scope.source)) {
                        var key = getKeyByItem(item);
                        if(key) {
                            delete $scope.source[key];
                        }
                        $scope.output = null;
                    }
                }

                $scope.view = function (item) {
                    if (item) {
                        if(item.view === undefined){
                            item.view = false;
                        }else
                        if (item.view === false) {
                            item.view = true;
                        }else
                        if(item.view === true) {
                            item.view = false;
                        }
                    }
                }

                $scope.moveUp = function (item,disabled) {
                    if(disabled) return;
                    if($.isArray($scope.source)){
                        var index = getIndexByItem(item);
                        var _temp = $scope.source[index];
                        $scope.source[index] = $scope.source[index-1];
                        $scope.source[index-1] = _temp;
                    }
                }

                $scope.moveDown = function (item, disabled) {
                    if(disabled) return;
                    if($.isArray($scope.source)){
                        var index = getIndexByItem(item);
                        var _temp = $scope.source[index];
                        $scope.source[index] = $scope.source[index+1];
                        $scope.source[index+1] = _temp;
                    }
                }

                $scope.$watch('options',function(options){
                    if ($.isPlainObject(options)) {
                        $scope.opts = $.extend({},defaults,options);
                    }
                });

                $scope.$watch('source',function(source){
                    $scope.sourceIsObject = $.isPlainObject(source);
                });

            }]

        }
    }])

    .directive('predefined',[function(){
        return {
            restrict: 'A',
            template: '<span><select ng-disabled="disabled" ng-model="value" ng-options="prop for prop in definedValues"></select></span>',
            replace : true,
            scope : {
                value : '=ngModel',
                disabled : '=ngDisabled'
            },
            link : function($scope, element, attr){
                $scope.propertyName = attr.predefined;
            },
            controller : ['$scope','CssDefaults', function($scope, CssDefaults){
                $scope.$watch('propertyName',function(newVal){
                    $scope.definedValues = CssDefaults.predefined[newVal];
                });

            }]

        }
    }])

    .directive('domPointer',['zxNodes', function(zxNodes){
        return {
            restrict: 'C',
            link : function($scope, element, attr){
                var pointers = [],
                    pointerLink = element,
                    zxNode;

                function createPointers(w,h,top,left) {
                    pointers.push($('<div class="zx__" id="zixys-pointer" style="width:'+w+'px;height:'+h+'px;top:'+top+'px;left:'+left+'px; position: absolute;"></div>').appendTo('body'));
                }
                function removePointers(){
                    while (pointers.length>0) {
                        pointers.pop().remove();
                    }
                }

                pointerLink.mouseover(function(){
                    if(!zxNode || !zxNode.nodes){
                        return;
                    }

                    for(var i=0; i<zxNode.nodes.length; i++){
                        var el = $(zxNode.nodes[i]);
                        createPointers(el.outerWidth(),el.outerHeight(),el.offset().top, el.offset().left);
                    }
                }).mouseout(function(){
                        removePointers();
                });

//                $scope.$on('selectElement',function(event, zixysNode){
//                    zxNode = zixysNode;
//                });

                $scope.zxNodes = zxNodes;
                $scope.$watch('zxNodes.selected',function(zixysNode){
                    zxNode = zixysNode;
                });

            },
            controller : ['$scope',function($scope){

            }]

        }
    }])

;

